/**
 * 复习 手写vue2.0 响应式原理
 */

/**
 * 判断是否是对象
 * @param object
 */
function isObject(object){
    return typeof object === 'object' || object === null
}

// 获取原生数组的原型
const oldArrayProto = Array.prototype
// 继承原生数组的原型
const proto = Object.create(oldArrayProto)
// 重写数组的7个方法
const arrayMethods = 'push shift unshift splice reverse pop sort'.split(' ')
for (const method of arrayMethods) {
    proto[method] = function (){
        // 劫持
        updateView()
        oldArrayProto[method].call(this,...arguments)
    }
}
/**
 * 观察
 * @param target
 */
function observe(target){
    if(!isObject(target)){
        // 不是对象 直接返回
        return target
    }

    for (const key in target) {
        reactive(target, key, target[key])
    }
}

/**
 * 创建响应式对象
 * @param target
 * @param key
 * @param value
 */
function reactive(target, key, value){
    // console.log(value);
    if(isObject(value)){
        // 如果value 是对象 继续遍历 创建响应式对象
        observe(value)
    }
    if(Array.isArray(target)){
        // 如果是数组 重设原型链指向
        Object.setPrototypeOf(target,proto)
    }
    Object.defineProperty(target,key,{
        get(){
            // console.log('get')
            return value
        },
        set(newVal){
            if(newVal !== value){
                if(isObject(newVal)){
                    // 如果newVal 值是对象 继续遍历 创建响应式对象
                    observe(newVal)
                }
                console.log('set')
                value = newVal
                updateView()
            }
        }
    })
}

/**
 * 更新视图
 */
function updateView(){
    console.log('更新视图')
}

/**
 * 1 处理简单的一级的对象属性
 */
const obj = {
    a: 1,
}
observe(obj)
obj.a = 12
console.log(obj.a)

/**
 * 2 处理多级对象属性
 */
/*const obj = {
    a: {
        b: 1
    },
}
observe(obj)
obj.a.b = 12
console.log(obj.a.b)*/

/**
 * 3 处理 直接赋值是对象 然后修改属性无法响应
 */
/*const obj = {
    a: 1,
}
observe(obj)
obj.a = {b: 12}
obj.a.b = 13
console.log(obj.a.b)*/

/**
 * 4 不存在的属性 无法响应 因为递归时没有这个属性 无法创建响应式对象
 */
/*const obj = {
    a: 1,
}
observe(obj)
obj.b = 14
console.log(obj.b)*/

/**
 * 5 处理数组 push shift unshift splice reverse pop sort
 */
/*const obj = {
    a: [1,2,3,4,5],
}
observe(obj)
// obj.a.push(4)
// obj.a.reverse()
// obj.a.pop()
// obj.a.splice(4,1)
// obj.a.shift()
// obj.a.unshift()
obj.a.sort()
console.log(obj.a)*/
